#!/usr/bin/env ruby

require "date"
require "optparse"

def run(command, abort_on_fail: true)
  puts "> #{command}" if $VERBOSE

  system(command, exception: abort_on_fail)
rescue StandardError => e
  raise "#{command.inspect} failed: #{e}"
end

remote = ENV.fetch("FOREM_RELEASE_REMOTE",  "origin")
source = ENV.fetch("FOREM_RELEASE_FROM",    "main")
target = "#{ENV.fetch('FOREM_RELEASE_CHANNEL', 'stable')}-next"

OptionParser.new ARGV.dup do |options|
  options.banner = <<~USAGE
    Usage: #{$PROGRAM_NAME} [options]

    Staging banches are named CHANNEL-next. Example: #{target}

  USAGE

  options.on "-c", "--channel CHANNEL",
             "Specify the release channel (defaults to #{target.sub(/-next$/, '').inspect})" do |release_channel|
    target = "#{release_channel}-next"
  end

  options.on "-f", "--from BRANCH/COMMIT/TAG",
             "Specify the source branch for this release (defaults to #{source.inspect})" do |from_branch|
    source = from_branch
  end

  options.on "-r", "--remote REMOTE", "Git remote to push to (defaults to #{remote.inspect})" do |git_remote|
    remote = git_remote
  end

  options.on "-v", "--verbose", "Enable verbose mode" do
    $VERBOSE = true
  end
end.parse!

original_branch = `git branch --show-current`.strip

begin
  puts "Fetching from #{remote}..."
  [source, target].each do |branch|
    run "git checkout --quiet #{branch}"
    run "git pull --ff-only --quiet #{remote} #{branch}"
    puts "Pulled latest #{branch.inspect}"
  end

  run "git merge --quiet #{source}"
  puts "Merged latest #{source} into #{target}"

  run "git push --quiet #{remote} #{target}"
  puts "Pushed #{target}, run the following to release:"
  puts "    scripts/release --channel #{target.sub(/-next$/, '')} --remote #{remote} --from #{target}"
ensure
  # Go back to the branch we were on before running this script
  run "git checkout --quiet #{original_branch}"
end
